package org.monitoringtools.elements.impl;

import static org.monitoringtools.util.AssertUtil.assertNotNull;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

public class TimeBasedCounter extends BasicCounter {

    private int delta;

    private long lastRefreshTime = 0L;

    private final Logger logger = Logger.getLogger(getClass());

    private TimeUnit timeUnit;

    public TimeBasedCounter(String id, TimeUnit timeUnit, Integer delta) {
        super(id);
        assertNotNull(timeUnit, delta);

        this.timeUnit = timeUnit;
        this.delta = delta;
        this.lastRefreshTime = System.currentTimeMillis();
    }

    public synchronized int getDelta() {
        return delta;
    }

    public synchronized long getLastRefreshTime() {
        return lastRefreshTime;
    }

    public synchronized TimeUnit getTimeUnit() {
        return timeUnit;
    }

    public synchronized void log(final boolean isSuccess) {
        refreshIfNeeded();
        super.log(isSuccess);
    }

    public synchronized void reset() {
        reset(System.currentTimeMillis());
    }

    @Override
    public String toString() {
        return "TimeBasedCounter [delta=" + delta + ", lastRefreshTime=" + (lastRefreshTime == 0 ? "N/A" : new Date(lastRefreshTime)) + ", logger="
                + logger + ", timeUnit=" + timeUnit + ", failure()=" + failure() + ", getId()=" + getId() + ", success()=" + success() + ", total()="
                + total() + "]";
    }

    private synchronized boolean isShouldRestart(final long currentTimeMillis) {
        return (currentTimeMillis - this.lastRefreshTime) > this.timeUnit.toMillis(this.delta);
    }

    private void refreshIfNeeded() {
        final long current = System.currentTimeMillis();
        if (isShouldRestart(current)) {
            if (logger.isDebugEnabled())
                logger.debug(new Date() + " isShouldRestart" + "\tlast: " + this.lastRefreshTime + "\tcurrent: " + current);

            reset(current);
        }
    }

    private synchronized void reset(long current) {
        super.reset();
        this.lastRefreshTime = current;
    }
}
